#include "cyclone_lexer_base.h"
#include "cpp-gen/CommonLexer.h"

namespace cyclone::parser
{
    using namespace antlr4;
    using namespace cyclone;

    CycloneLexerBase::CycloneLexerBase(CharStream *input) : Lexer(input) {}
    
    CycloneLexerBase::~CycloneLexerBase(){}

    bool CycloneLexerBase::getStrictDefault() { return useStrictDefault; }

    void CycloneLexerBase::setUseStrictDefault(bool value)
    {
        useStrictDefault = value;
        useStrictCurrent = value;
    }

    bool CycloneLexerBase::IsStrictMode() { return useStrictCurrent; }

    std::unique_ptr<antlr4::Token> CycloneLexerBase::nextToken()
    {
        auto next = Lexer::nextToken();

        if (next->getChannel() == Token::DEFAULT_CHANNEL)
        {
            // Keep track of the last token on the default channel.
            lastToken = true;
            lastTokenType = next->getType();
        }

        return next;
    }

    void CycloneLexerBase::ProcessOpenBrace()
    {
        useStrictCurrent = scopeStrictModes.size() > 0 && scopeStrictModes.top() ? true : useStrictDefault;
        scopeStrictModes.push(useStrictCurrent);
    }

    void CycloneLexerBase::ProcessCloseBrace()
    {
        if (scopeStrictModes.size() > 0)
        {
            useStrictCurrent = scopeStrictModes.top();
            scopeStrictModes.pop();
        }
        else
        {
            useStrictCurrent = useStrictDefault;
        }
    }

    void CycloneLexerBase::ProcessStringLiteral()
    {
        if (lastToken || lastTokenType == CommonLexer::OpenBrace)
        {
            std::string text = getText();
            if (text == "\"use strict\"" || text == "'use strict'")
            {
                if (scopeStrictModes.size() > 0)
                    scopeStrictModes.pop();
                useStrictCurrent = true;
                scopeStrictModes.push(useStrictCurrent);
            }
        }
    }

    bool CycloneLexerBase::IsRegexPossible()
    {
        if (lastToken)
        {
            // No token has been produced yet: at the start of the input,
            // no division is possible, so a regex literal _is_ possible.
            return true;
        }

        switch (lastTokenType)
        {
        case CommonLexer::Identifier:
        case CommonLexer::NullLiteral:
        case CommonLexer::BooleanLiteral:
        case CommonLexer::This:
        case CommonLexer::CloseBracket:
        case CommonLexer::CloseParen:
        case CommonLexer::OctalIntegerLiteral:
        case CommonLexer::DecimalLiteral:
        case CommonLexer::HexIntegerLiteral:
        case CommonLexer::StringLiteral:
        case CommonLexer::PlusPlus:
        case CommonLexer::MinusMinus:
            // After any of the tokens above, no regex literal can follow.
            return false;
        default:
            // In all other cases, a regex literal _is_ possible.
            return true;
        }
    }

    bool CycloneLexerBase::IsInTemplateString() { return templateDepth > 0; }

    void CycloneLexerBase::IncreaseTemplateDepth() { ++templateDepth; }

    void CycloneLexerBase::DecreaseTemplateDepth() { --templateDepth; }

} // namespace cyclone::parser
